Storybook で複数 Theme の切り替えを可能にする
Storybook のアドオン、React Themingを使うと Storybook 上で複数の Theme 切り替えができるようになります。
できたもの
前提条件
React + Typescript で実装された既存のプロジェクトに Storybook を導入し、Theme 切り替えができるようにします。
- React(CRA) 17.0.2
- Typescript 4.1.2
- emotion 11
- Storybook 6.3.8
React のプロジェクトをクローン
こちらの既存の React プロジェクトをクローンします。
左のメニューから Zip で落とすことができるので、VSCode で開いてyarn
コマンドで依存をダウンロードします。
Storybook
先ほど落としてきたプロジェクトに Storybook を導入します
npx sb init
yarn storybook
を実行して以下の画面が立ち上がれば OK です。
Story を追加
クローンしたサンプルに Story を追加します。
不要なファイルを削除
Introduction.stories.mdx
以外のファイルは利用しないので削除します。Introductionもよしなに更新してください。
MembersCard.stories.tsx を追加
以下の Story をstories
へ追加します。
import React from 'react' import { Story, Meta } from '@storybook/react/types-6-0' import { MembersCard } from './../components/MembersCard' export default { title: 'pages/MembersCard', component: MembersCard, parameters: { docs: { description: { component: 'MembersCard', }, }, }, } as Meta const Template: Story = (args: any) => ( <MembersCard {...args}></MembersCard> )
emotion の Theming を利用しているため、このままだと Theme が正常に読み込まれません。次のステップで.stories/previes.js
でReact Theming アドオン を設定します。
React Theming をインストール
## npm npm i --save-dev @react-theming/storybook-addon ## or yarn yarn add --dev @react-theming/storybook-addon
emotion-theming
も利用するのでインストールしておきます。
yarn add --dev emotion-theming
main.js を更新
main.js
を以下のように更新してアドオンを追加します。
module.exports = { stories: ["../src/**/*.stories.mdx", "../src/**/*.stories.@(js|jsx|ts|tsx)"], addons: [ "@storybook/addon-links", "@storybook/addon-essentials", "@storybook/preset-create-react-app", "@react-theming/storybook-addon", ], };
preview.js を更新
StorybookのDecorator機能を利用してThemeProviderを設定します。
####preview.js
import React from "react"; import styled from "@emotion/styled"; import {ThemeProvider} from "emotion-theming"; import {addDecorator} from "@storybook/react"; import {withThemes} from "@react-theming/storybook-addon"; import {pink, yellow, sky} from "../src/themes/theme"; addDecorator(withThemes(ThemeProvider, [pink, yellow, sky])); const PageDefaultStyle = styled.div` font-family: Hiragino Sans; `; export const decorators = [ (Story) => ( <PageDefaultStyle> <Story /> </PageDefaultStyle> ), ];
Emotionを利用する場合はemotion-theming
を使ってください。@emotion/react
等だと正常にThemeが読み込まれません。
themes/theme.ts
切り替えたいThemeの定義です。
export const pink = { fonts: { mainFont: 'Avenir Next, sans-serif', subFont: 'Hira Kaku Pro N, sans-serif', textFont: 'Hiragino Sans', numberFont: 'Avenir Next, sans-serif', }, colors: { mainColor: '#64363C', subTextColor: '#8E354A', lineColor: '#E6E5E4', backgroundColor: '#F8C3CD', titleBackgroudColor: '#F8F4F4', accentColor: '#EB7A77', stageColor: '#CB1B45', }, } export const yellow = { fonts: { mainFont: 'Times New Roman', subFont: 'Garamond', textFont: 'Tahoma', numberFont: 'Times New Roman', }, colors: { mainColor: '#5B622E', subTextColor: '#8D742A', lineColor: '#E6E5E4', backgroundColor: '#DCB879', titleBackgroudColor: '#EFBB24', accentColor: '#212121', stageColor: '#90B44B', }, } export const sky = { fonts: { mainFont: 'Impact', subFont: 'Tahoma, sans-serif', textFont: 'Impact', numberFont: 'Impact', }, colors: { mainColor: '#6c756b', subTextColor: '#8D8D8D', lineColor: '#E6E5E4', backgroundColor: '#F3F4F5', titleBackgroudColor: '#96C5F7', accentColor: '#212121', stageColor: '#4D565D', }, }
最後に
本記事ではStorybookとReact Themingを使ってThemeを切り替えた表示をStorybook上で実現する方法をまとめました。サンプルはPageのみにStoryを追加しましたが、Atoms, Molecures別にStoryを追加した場合でも同様にThemeを切り替えてStorybook上でUIを確認できるので複数Themeの要件があるプロジェクトではとても便利です。何かの参考になれれば幸いです。